/***************************************************************************
 * OWEBFOLDER.H
 *
 *  The Office Web Folder Client Sample
 *
 *  A Test Application Using the Microsoft Data Access Internet Publishing
 *  Provider (MSDAIPP) to view, upload, and download files and folders from
 *  a FPSE or WebDAV web share.
 *
 *  Copyright (c)1999-2003; Microsoft Corporation, All rights reserved.
 *  Written by DSOI Office Integration, Microsoft Developer Support
 *
 *  You have a royalty-free right to use, modify, reproduce and distribute
 *  this sample application, and/or any modified version, in any way you
 *  find useful, provided that you agree that Microsoft has no warranty,
 *  obligations or liability for the code or information provided herein.
 *
 *  THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 *  EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 ***************************************************************************/
#ifndef OWEBFOLDER_H
#define OWEBFOLDER_H

///////////////////////////////////////////////////////////////////////////////////
// Building for Windows 98/ME, Windows 2000 and Windows XP (this app may fail to 
// work properly on Windows 95 and Windows NT4 pre-SP4 machines unless those
// clients upgrade their versions of IE, MDAC, and DCOM on their own)...
#define WINVER                 0x0400
#define WIN32_LEAN_AND_MEAN
#define _WIN32_DCOM

///////////////////////////////////////////////////////////////////////////////////
// Disable warnings that can be safely ignored...
//
#pragma warning(disable: 4100) // unreferenced formal parameter
#pragma warning(disable: 4201) // nameless unions are part of C++
#pragma warning(disable: 4514) // unreferenced inline function has been removed
#pragma warning(disable: 4786) // identifier was truncated in the debug information

#include <windows.h>
#include <commdlg.h>
#include <commctrl.h>
#include <ole2.h>

#include "msdaipp2.h"        // The include for MSDAIPP version 2.0
#include "utilities.h"       // Common utilities shared by all classes
#include ".\res\resource.h"

///////////////////////////////////////////////////////////////////////////////////
// Forward declares of the main classes (descibed here)...
//
class CMSDAIPPSession;      // MSDAIPP Session object (controls HTTP session)
class CMSDAIPPRowset;       // MSDAIPP Rowset object (controls folder data)
class COfficeWebFolder;     // Web Folder view bound to client app's listview 
class COfficeWebClientApp;  // Main client application and UI class


///////////////////////////////////////////////////////////////////////////////////
// MSDAIPP_xxxx Structs - Used for direct data binding and passing info.
//
//  MSDAIPP_SESSIONINFO - Contains binding info to start a session. Passed to the
//                        CMSDAIPPSession object when opening a new web folder. 
//
//  MSDAIPP_ROWSETINFO  - Contains information about a file/folder on the web site.
//                        This data is returned by CMSDAIPPRowset to the client and
//                        the struct allows for direct binding via IAccessor.
//
//  MSDAIPP_COLLECTIONINFO   - Used in binding to make a new collection (sub folder).
//
//  MSDAIPP_ACCESSORBINDINGS - Helper in setting up the bindings.
//
#define OWF_CACHEAGGRESSIVELY       0x04
#define OWF_TREATASOFFLINE          0x10
#define OWF_FLUSHWININETPWCACHE		0x20
#define OWF_CUSTOMUSERAGENT         0x40
#define OWF_DAV_USELOCKDISCOVERY    0x100
#define OWF_WEC_SHOWTHICKETFILES    0x200

typedef struct //MSDAIPP_SESSIONINFO
{
	CHAR   szDataSource[MSDAIPP_MAX_URL_LENGTH];
	CHAR   szLockOwner[MAX_PATH];
	DWORD  grfBindFlags;
	DWORD  grfProviderFlags;
    DWORD  grfEncodingType;
	GUID   uidProtocolProvider;
	HWND   hwnd;
	LCID   lcid;
	UINT   uiProviderVersion;
} MSDAIPP_SESSIONINFO, *LP_MSDAIPP_SESSIONINFO;

typedef struct //MSDAIPP_ROWSETINFO
{
	WCHAR         wszURL[MSDAIPP_MAX_URL_LENGTH];
	WCHAR         wszDisplayName[MAX_PATH];
	WCHAR         wszContentType[MAX_PATH];
	DWORDLONG     ddwStreamSize;
    FILETIME      ftCreateTime;
	FILETIME      ftLastModified;
    VARIANT_BOOL  bIsSubFolder;
    VARIANT_BOOL  bIsReadOnly;
    VARIANT_BOOL  bIsHidden;
    VARIANT_BOOL  bIsMarkedOffline;
} MSDAIPP_ROWSETINFO, *LPMSDAIPP_ROWSETINFO;

typedef struct //MSDAIPP_COLLECTIONINFO
{
	WCHAR         wszName[MAX_PATH];
    VARIANT_BOOL  bIsSubFolder;
    VARIANT_BOOL  bIsHidden;
} MSDAIPP_COLLECTIONINFO, *LPMSDAIPP_COLLECTIONINFO;

typedef struct //MSDAIPP_ACCESSORBINDINGS
{
	LPOLESTR      pwszColumnName;
	DBTYPE        wColType;
	ULONG         ulMaxSize;
} MSDAIPP_ACCESSORBINDINGS, *LP_MSDAIPP_ACCESSORBINDINGS;


///////////////////////////////////////////////////////////////////////////////////
// CMSDAIPPSession  -  Wrapper for MSDAIPP Session object
//
// This class controls access to a given web session with a particular server. It
// also creates and holds the main MSDAIPP DSO object and Session. Bind properties
// are passed to initialize the new session and gain the first record set.
//
class CMSDAIPPSession : public IUnknown
{
public:
    CMSDAIPPSession(IDBInitialize* pdsoinit);
    ~CMSDAIPPSession(void);

 // Static creation routine to make a new CMSDAIPPSession object..
	static STDMETHODIMP_(CMSDAIPPSession*) CreateMsdaippDso();

 // Simple IUnknown Implementation
    STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){return E_NOINTERFACE;}
    STDMETHODIMP_(ULONG) AddRef(void){return ++m_cRef;}
    STDMETHODIMP_(ULONG) Release(void);

 // CMSDAIPPSession Public Functions
	STDMETHODIMP  CreateNewSession(LP_MSDAIPP_SESSIONINFO props);
	STDMETHODIMP  CreateRootRowset(CMSDAIPPRowset **ppMsdaippRowset);
	STDMETHODIMP_(BSTR) GetDataSourceURL();
	STDMETHODIMP_(void) ResetSession(){InternalCloseSession();}

 // Accessor Functions for private data...
	inline IUnknown* GetSessionObj(){return ((LPUNKNOWN)m_pSession);}
	inline UINT      GetServerType(){return m_iServerType;}
	inline UINT      GetMsdaippVersion(){return m_iProvVersion;}
	inline LPCSTR    GetMsdaippVersionStr(){return &m_szProvVersion[0];}

protected:
	STDMETHODIMP  InternalGetDsoVersion();
	STDMETHODIMP  InternalSetProperties(LP_MSDAIPP_SESSIONINFO props);
	STDMETHODIMP  InternalCreateSession();
	STDMETHODIMP  InternalCloseSession();

private:
	DWORD			m_cRef;
	IDBInitialize*  m_pDataSource;
	IOpenRowset*    m_pSession;
	UINT            m_iServerType;
	UINT            m_iProvVersion;
	CHAR            m_szProvVersion[128];
};

///////////////////////////////////////////////////////////////////////////////////
// CMSDAIPPRowset  -  Wrapper for MSDAIPP Rowset object
//
// This class controls the rowset for a given folder/subfolder, allowing us access
// to the elements in the "table" (web site). Multiple rowsets may exist for a given
// session object. The CMSDAIPPSession parent is cached for the life of this object.
//
//  TODO: Handle multi-file operations (move, copy, delete) via IScopedOperations.
//
class CMSDAIPPRowset : public IUnknown
{
public:
    CMSDAIPPRowset(LPCWSTR pwszURL, CMSDAIPPSession* pSession);
    ~CMSDAIPPRowset(void);

 // Static creation routine to make a new CMSDAIPPRowset object..
	static STDMETHODIMP_(CMSDAIPPRowset*) CreateMsdaippRowset(LPCWSTR pwszURL, CMSDAIPPSession* pSession);

 // IUnknown Implementation
    STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){return E_NOINTERFACE;}
    STDMETHODIMP_(ULONG) AddRef(void){return ++m_cRef;}
    STDMETHODIMP_(ULONG) Release(void);

 // CMSDAIPPRowset Public Functions
	STDMETHODIMP  OpenRowset(LPWSTR pwszRow, CMSDAIPPRowset **ppMsdaippRowset);
	STDMETHODIMP  GetNextFolderItem(LPMSDAIPP_ROWSETINFO pitem);
	STDMETHODIMP  ResetFolderList();
	STDMETHODIMP  AddNewCollection(LPCWSTR pwszFolderName, LPMSDAIPP_ROWSETINFO pitem);
    STDMETHODIMP  DownloadFile(LPMSDAIPP_ROWSETINFO pitem, LPCWSTR pwszFolder);
    STDMETHODIMP  UploadFile(LPCWSTR pwszFileToUpload, LPMSDAIPP_ROWSETINFO* ppitem);
	STDMETHODIMP  DeleteURLResource(LPCWSTR pwszUrlResource);
    STDMETHODIMP  ReloadRowset();

    inline LPWSTR GetFolderURL(){return m_bstrFolderURL;}

protected:
	STDMETHODIMP  InternalCreateAccessor(MSDAIPP_ACCESSORBINDINGS *paccinfo, ULONG cCols, IAccessor **ppAccessor, HACCESSOR *phAccessor);
	STDMETHODIMP  InternalGetFolderItems(ULONG citems, LPMSDAIPP_ROWSETINFO pitems, ULONG* pcfetched);
	STDMETHODIMP  InternalGetFolderItemFromURL(LPCWSTR pwszUrl, MSDAIPP_ROWSETINFO **ppitem);

private:
	DWORD			 m_cRef;
	CMSDAIPPSession* m_pIPPSession;
	IRowset*		 m_pRowset;
	IAccessor*       m_pAccessor;
	HACCESSOR        m_hAccessor;
    BSTR             m_bstrFolderURL;
};

///////////////////////////////////////////////////////////////////////////////////
// COfficeWebFolder  -  Very simple ListView presentation of CMSDAIPPRowset
//
// This object "owns" a given CMSDAIPPRowset folder/subfolder, and can render it
// to a ListView control on the host app. The class is a simple wrapper designed to
// incapsulate the listview functions and separate the host from the details of working
// with rowset.
//
//  TODO: Add support for multi-file drag-drop, context menus, and icon association.
//
class COfficeWebFolder : public IUnknown 
{
public:
    COfficeWebFolder(COfficeWebFolder* pparent, CMSDAIPPRowset* prowset, HWND hwnd);
    ~COfficeWebFolder(void);

 // Static creation routine to make a new COfficeWebFolder object..
	static STDMETHODIMP_(COfficeWebFolder*) CreateWebFolderView(COfficeWebFolder* pParent, CMSDAIPPRowset* pFolderRowset, HWND hwndList);

 // IUnknown Implementation
    STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
    STDMETHODIMP_(ULONG) AddRef(void){return ++m_cRef;}
    STDMETHODIMP_(ULONG) Release(void);

 // COfficeWebFolder Public Functions
	STDMETHODIMP PopulateListView();
	STDMETHODIMP CleanupListView(BOOL fFullRefresh);
	STDMETHODIMP OpenSubFolder(UINT idx, COfficeWebFolder** ppNewFolder);
	STDMETHODIMP CreateNewSubFolder(LPCWSTR pwszNewFolder);
    STDMETHODIMP DownloadFile(UINT idx, LPCWSTR pwszFolder);
    STDMETHODIMP UploadFile(LPCWSTR pwszFileToUpload);
    STDMETHODIMP DeleteItem(UINT idx);

 // Accessor Functions
	STDMETHODIMP_(INT) GetSelectedItemIndex();
	STDMETHODIMP_(LPMSDAIPP_ROWSETINFO) GetRowsetInfo(UINT idx);
	STDMETHODIMP_(BOOL) IsItemSubFolder(UINT idx);
	STDMETHODIMP_(BOOL) SetDisplayInfo(NMLVDISPINFO *plvdi);
	STDMETHODIMP_(COfficeWebFolder*) GetParentFolder(){return m_pParentFolder;}

    inline LPSTR GetFolderName(){return m_pszFolderName;}

	static INT CALLBACK ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

protected:

private:
	DWORD			  m_cRef;
	COfficeWebFolder* m_pParentFolder;
	CMSDAIPPRowset*   m_pIPPRowset;
	HWND              m_hwndList;
    LPSTR             m_pszFolderName;
};

///////////////////////////////////////////////////////////////////////////////////
// COfficeWebClientApp  -  Main Client Application.
//
// This object controls most user interaction and dialogs, and provides the basic
// framework for a simple Win32 SDI application. Not much of interest here except
// as a host for one or more COfficeWebFolder objects. 
//
class COfficeWebClientApp
{
public:
    COfficeWebClientApp(HINSTANCE hInstance);
    ~COfficeWebClientApp(void);

 // App init and message loop...
    BOOL    InitApplication(LPCSTR pszCmdLine, int nCmdShow);
    WPARAM  MessageLoop(void);

 // Command functions for menu operations...
    STDMETHODIMP_(BOOL) CmdOpenFolder();
    STDMETHODIMP_(BOOL) CmdCloseFolder();
    STDMETHODIMP_(BOOL) CmdCreateSubFolder();
    STDMETHODIMP_(BOOL) CmdDownloadFile();
    STDMETHODIMP_(BOOL) CmdUploadFile();
    STDMETHODIMP_(BOOL) CmdRenameFile();
    STDMETHODIMP_(BOOL) CmdDeleteFile();
    STDMETHODIMP_(BOOL) CmdSelectAll();
    STDMETHODIMP_(BOOL) CmdUpFolder();
    STDMETHODIMP_(BOOL) CmdRefreshView();
    STDMETHODIMP_(BOOL) CmdSwitchView(UINT vwid);

 // Main Window Message Handlers...
    void OnAppQuit();
    void OnPaint(HDC hDC, LPRECT lpUpdateRect);
    void OnSize(UINT State, int cx, int cy);
    void OnInitMenuPopup(HMENU hMenu, UINT uItem, BOOL fSystemMenu);
    void OnSetFocus();
	BOOL OnCommand(int id, HWND hwndCtl, UINT codeNotify);
	BOOL OnNotify(int id, LPNMHDR pnmhdr);
    BOOL OnQueryClose();

    inline HWND GetMainWindow(){return m_hwndApp;}

	static LRESULT CALLBACK ClientAppWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
	static BOOL    CALLBACK OpenFolderWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
	static BOOL    CALLBACK ShowFilePropWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
	static BOOL    CALLBACK NewFolderNameWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);

protected:
    STDMETHODIMP        InternalOpenSubFolderView(UINT id);
    STDMETHODIMP        InternalDisplayFileProps(UINT id);
    STDMETHODIMP_(void) InternalSetStatusBarFolderName();        

private:
	HINSTANCE			m_hInstance;
	HCURSOR             m_curArrow;
	HCURSOR             m_curWait;
    HACCEL				m_hAccel;           // Accellerators
	HMENU               m_hmnuMainMenu;
    HWND				m_hwndApp;          // Window handle of main frame
    HWND				m_hwndStatus;       // Status Bar
	HWND				m_hwndListView;     // List View
	HIMAGELIST			m_himlIcons;
	HIMAGELIST			m_himlSmIcons;
	COfficeWebFolder*   m_pRootFolder;
	COfficeWebFolder*   m_pCurrentFolder;
	BOOL                m_fROSession;
};

// We will make the host app a global object (for simpler code)...
extern COfficeWebClientApp* g_theApp;

#endif //OWEBFOLDER_H